//
//  Player.m
//  PacIsBack
//
//  Created by Jérémy Brault on 14/12/09.
//  Copyright 2009 None. All rights reserved.
//

#import "PlayerCharacter.h"
#import "BattleTeamProtocol.h";
#import "BattleProtocol.h";
#import "CharacterViewController.h";
#import "BattleViewController.h"
#import "ExperienceTableProtocol.h"
#import "TablesFactory.h"
#import "AbilityProtocol.h"
#import "AttackAbility.h"
#import "StatsTableProtocol.h"
#import "SkillsGainedTableProtocol.h"
#import "DoubleAttack.h"

@implementation PlayerCharacter

@synthesize battleController, level, currentHP, maxHP, currentMP, maxMP, currentXP, strength, agility, vitality, defense, intelligence, wisdom, speed, luck, experienceReward, experienceTable, statsTable, skillsTable, characterType, team, manualyPlayed, hasPlayed, selected, availableSkills;

- (id)initWithType:(NSString*) type andTeam:(id<BattleTeamProtocol>) characterTeam{
	if (self = [self initWithType:type]) {
		[self setTeam:characterTeam];
	}
	
	return self;
}
- (id)initWithType:(NSString*) type{
	if (self = [super init]) {
		[self setCharacterType:type];
		[self setExperienceTable:[TablesFactory experienceTableForCharacter:[self characterType]]];
		[self setStatsTable:[TablesFactory statsTableForCharacter:[self characterType]]];
		[self setSkillsTable:[TablesFactory skillsTableForCharacter:[self characterType]]];
		[self setLevel:1];
		[self setMaxHP:1000];
		[self setCurrentHP:1000];
		[self setMaxMP:1000];
		[self setCurrentMP:1000];
		[self setCurrentXP:0];
		[self setStrength:10];
		[self setAgility:10];
		[self setVitality:10];
		[self setDefense:10];
		[self setIntelligence:10];
		[self setWisdom:10];
		[self setSpeed:10];
		[self setLuck:10];
		[self setExperienceReward:20];
		CharacterViewController* charViewController = [[CharacterViewController alloc] initCharacterControllerForModel:self];
		[self setBattleController:charViewController];
		[charViewController release];
		[self setManualyPlayed:YES];
		[self setHasPlayed:NO];
		id<AbilityProtocol> attackAbility = [[AttackAbility alloc] init];
		NSMutableArray* initialSkills = [[NSMutableArray alloc] init];
		[initialSkills addObject:attackAbility];
		[attackAbility release];
		[self setAvailableSkills:initialSkills];
		[initialSkills release];
	}
	
	return self;
}

- (void) gainExperience:(NSInteger) experienceValue{
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",experienceValue, @" Experience points "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
	NSInteger newExperience = experienceValue+[self currentXP];
	while (newExperience>[[self experienceTable] requiredExperienceForLevel:[self level]]) {
		newExperience = newExperience-[[self experienceTable] requiredExperienceForLevel:[self level]];
		[self gainLevel];
	}
	[self setCurrentXP:newExperience];
}

- (void) gainLevel{
	[self setLevel:[self level]+1];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d",[self characterType],@" has obtained level ",[self level]];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
	[self gainHpMax:[[self statsTable] HPGainedAtLevel:[self level]]];
	[self gainMpMax:[[self statsTable] MPGainedAtLevel:[self level]]];
	[self gainStrengh:[[self statsTable] strenghGainedAtLevel:[self level]]];
	[self gainAgility:[[self statsTable] agilityGainedAtLevel:[self level]]];
	[self gainVitality:[[self statsTable] vitalityGainedAtLevel:[self level]]];
	[self gainDefence:[[self statsTable] defenceGainedAtLevel:[self level]]];
	[self gainIntelligence:[[self statsTable] intelligenceGainedAtLevel:[self level]]];
	[self gainWisdom:[[self statsTable] wisdomGainedAtLevel:[self level]]];
	[self gainLuck:[[self statsTable] luckGainedAtLevel:[self level]]];
	[self gainSkills:[[self skillsTable] skillsGainedAtLevel:[self level]]];
	[self gainExpReward:[[self statsTable] expRewardGainedAtLevel:[self level]]];
	[self recreateBattleController];
}

-(void) gainSkills:(NSArray*) skills{
	for (id<AbilityProtocol> ability in skills) {
		[[self availableSkills] addObject:ability];
		if ([self currentBattle]!=nil) {
			NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%@",[self characterType],@" has learned ",[ability shownName]];
			[[self currentBattle] showInfo:texte];
			[texte release];
		}
	}
}

-(void) gainHpMax:(NSInteger) value{
	[self setMaxHP:[self maxHP]+value];
	[self setCurrentHP:[self maxHP]];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" Hp "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainMpMax:(NSInteger) value{
	[self setMaxMP:[self maxMP]+value];
	[self setCurrentMP:[self maxMP]];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" Mp "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainStrengh:(NSInteger) value{
	[self setStrength:[self strength]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" strengh "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainAgility:(NSInteger) value{
	[self setAgility:[self agility]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" agility "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainVitality:(NSInteger) value{
	[self setVitality:[self vitality]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" vitality "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainDefence:(NSInteger) value{
	[self setDefense:[self defense]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" defense "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainIntelligence:(NSInteger) value{
	[self setIntelligence:[self intelligence]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" intelligence "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainWisdom:(NSInteger) value{
	[self setWisdom:[self wisdom]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" wisdom "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainLuck:(NSInteger) value{
	[self setLuck:[self luck]+value];
	if ([self currentBattle]!=nil) {
		NSString* texte = [[NSString alloc] initWithFormat:@"%@%@%d%@",[self characterType],@" has gained ",value, @" luck "];
		[[self currentBattle] showInfo:texte];
		[texte release];
	}
}

-(void) gainExpReward:(NSInteger) value{
	[self setExperienceReward:[self experienceReward]+value];
}

-(void) trySelecting{
	[[self currentBattle] trySelecting:self];
}

-(void) select{
	[self setSelected:YES];
}

-(void) unselect{
	[self setSelected:NO];
}

-(void) doAction{
	[self setHasPlayed:NO];
	if ([self manualyPlayed]) {
		while (![self hasPlayed]) {
			
		}
	}
	else {
		NSArray* availablePlayerTargets = [[[self currentBattle] playerTeam] characters];
		NSThread* threadAttack = [[NSThread alloc] initWithTarget:self selector:@selector(threadedAttack:) object:[availablePlayerTargets objectAtIndex:0]];
		[threadAttack start];
		[threadAttack autorelease];
		while (![self hasPlayed]) {
			
		}
	}

}

- (BOOL) isAlive{
	return [self currentHP]>0;
}

-(id<BattleProtocol>) currentBattle{
	return [[self team] currentBattle];
}

-(NSInteger) attackPower{
	//return 100000;
	NSInteger attackPower = ([self strength]*10)+([self agility]/2)+([self luck]/10);
	if ((rand()%100)>(50-luck)) {
		attackPower = attackPower*2;
	}
	return attackPower;
}

-(NSInteger) receiveAttack:(NSInteger) originAttackPower{
	CGFloat defenceMultiplier = (100.0-[self defense])/100.0;
	NSInteger luckReduce = [self luck]/10;
	NSInteger vitalityReduce = [self vitality]/5;
	NSInteger realDamages = (((originAttackPower*defenceMultiplier)-luckReduce)-vitalityReduce);
	if ((rand()%100)>(50-luck)) {
		realDamages = realDamages/2;
	}
	NSInteger newHP = [self currentHP] - realDamages;
	if (newHP > 0) {
		[self setCurrentHP:newHP];
	}
	else {
		[self setCurrentHP:0];
		[[self battleController] animateDeath];
	}
	return realDamages;
}

-(NSComparisonResult) isFasterThan:(id<CharacterProtocol>) compared{
	if ([self speed] > [compared speed]) {
		return NSOrderedDescending;
	}
	else if ([self speed] == [compared speed]) {
		return NSOrderedSame;
	}
	else {
		return NSOrderedAscending;
	}
}

-(void) threadedAttack:(id<CharacterProtocol>) target{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[[self currentBattle] setSelectedAbility:[[self availableSkills] objectAtIndex:0]];
	[[self currentBattle] processCurrentActionFrom:self on:target];
	[pool release];
}

-(void) recreateBattleController{
	CharacterViewController* charViewController = [[CharacterViewController alloc] initCharacterControllerForModel:self];
	[self setBattleController:charViewController];
	[charViewController release];
}

-(void) useMP:(NSInteger) cost{
	if ([self currentMP]> cost) {
		[self setCurrentMP:[self currentMP]-cost];
	}
	else {
		[self setCurrentMP:0];
	}
	[[self battleController] changeMana:[self currentMP]];
}

-(void) regenerationTick{
	NSInteger hpRestaured = ([self maxHP]/100)+[self vitality];
	NSInteger mpRestaured = ([self maxMP]/10)+[self wisdom];
	if (([self currentHP]+hpRestaured)>[self maxHP]) {
		[self setCurrentHP:[self maxHP]];
	}
	else {
		[self setCurrentHP:[self currentHP]+hpRestaured];
	}
	if (([self currentMP]+mpRestaured)>[self maxMP]) {
		[self setCurrentMP:[self maxMP]];
	}
	else {
		[self setCurrentMP:[self currentMP]+mpRestaured];
	}
	[[self battleController] changeHealth:[self currentHP]];
	[[self battleController] changeMana:[self currentMP]];
}

- (void) dealloc{
	[self setBattleController:nil];
	[self setExperienceTable:nil];
	[self setStatsTable:nil];
	[self setSkillsTable:nil];
	[self setCharacterType:nil];
	[self setTeam:nil];
	[self setAvailableSkills:nil];
	[super dealloc];
}

@end
